#include <kernel/system.h>
#include <kernel/screen.h>
#include <kernel/types.h>

#include <lib/string.h>


uint16_t *videomem = (uint16_t *)(VIDEO_MEM);

int x = 0;
int y = 0;
unsigned char attrib = ATTRIB(ATT_LGREY, ATT_BLACK);

#define COMBINE(c, a) ((uint16_t)(c) | (uint16_t)((a) << 8))

void move_cursor(int _x, int _y)
{
	unsigned short pos = _y*WIDTH + _x;
	
	outportb(0x3D4, 14);
	outportb(0x3D5, (unsigned char)pos >> 8);
	outportb(0x3D4, 15);
	outportb(0x3D5, (unsigned char)pos );
}

void _putch(const char ch)
{
	switch(ch) {
		case '\n':
			y++;
			x = 0;
			break;
		case '\t':
			break;
		default:
			*(videomem + WIDTH*y + x++) = COMBINE(ch, attrib);
	}
	
	if(x == WIDTH) {
		x = 0;
		y++;
	}
	if(y == HEIGHT) {
		y = HEIGHT-1;
		memcpy(videomem+WIDTH, videomem, (WIDTH-1)*HEIGHT*2); 
	}
	
}

/* 
 * puts an integer on the screen, without moving the cursor
 * returs the length of the string put on the screen
 *        or -1 on error
 */
int _putint(int num, const int base)
{
	const char nums[] = "0123456789ABCDEF";
	int b, i;
	char buf[32];
	
	if(base < 2 || base > 16)
		return -1;
	
	b = 0;
	do {
		buf[b++] = nums[num % base];
		num = (int) num / base;
	} while(num);
	
	for(i=b-1; i>=0; i--)
		_putch(buf[i]);
	return b;
}

void putint(int num, int base)
{
	_putint(num, base);
	move_cursor(x, y);
}

void putch(const char ch)
{
	_putch(ch);
	move_cursor(x, y);
}

void puts(const char *str)
{
	for(; *str; str++) {
		_putch(*str);
	}
	_putch('\n');
	move_cursor(x, y);
}

void set_attrib(const unsigned char att)
{
	attrib = att;
}

void clear(void)
{
	int i;
	
	for(i=0; i<HEIGHT*WIDTH; i++) {
		*(videomem + i) = COMBINE(' ', attrib);
	}
	x = y = 0;
	move_cursor(0, 0);
}
